package com.syh.jn.scm.infrastructure.repository.impl.operation.system;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.util.other.IdWorker;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.syh.core.ddd.infrastructure.repository.AbstractAggregateRepository;
import com.syh.core.ddd.infrastructure.repository.AggregateRepoHibernateImplTmpl;
import com.syh.core.expction.DataModelException;
import com.syh.jn.scm.domain.operation.entity.system.OperationMenu;
import com.syh.jn.scm.domain.operation.repository.system.OperationMenuRepository;
import com.syh.jn.scm.domain.operation.repository.system.PermissionRepository;
import com.syh.jn.scm.domain.supplier.entity.stock.StockRecord;
import com.syh.jn.scm.domain.supplier.entity.stock.StockRecordItem;
import com.syh.jn.scm.dto.operation.system.menu.OperaMenuVo;
import com.syh.jn.scm.infrastructure.repository.model.stock.StockRecordItemModel;
import com.syh.jn.scm.infrastructure.repository.model.stock.StockRecordModel;
import com.syh.jn.scm.infrastructure.repository.model.system.MenuModel;
import com.syh.jn.scm.infrastructure.repository.model.system.MenuPermissionModel;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import com.syh.jn.scm.infrastructure.wrapper.BaseResolve;
import com.syh.jn.scm.infrastructure.wrapper.ResolveToSQL;
import lombok.SneakyThrows;
import org.apache.ibatis.jdbc.SQL;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.stereotype.Repository;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

@Repository
public class OperationMenuRepositoryImpl implements OperationMenuRepository {

  private HibernateTemplate hibernateTemplate;

  private AggregateRepoHibernateImplTmpl<OperationMenu, MenuModel, Long> operationMenuRepoHibernateImplTmpl;


  @Autowired
  public OperationMenuRepositoryImpl(HibernateTemplate hibernateTemplate) {
    this.hibernateTemplate = hibernateTemplate;
    operationMenuRepoHibernateImplTmpl =
            new AggregateRepoHibernateImplTmpl.Builder()
                    .hibernateTemplate(hibernateTemplate)
                    .idClass(Long.class)
                    .entityClass(OperationMenu.class)
                    .modelClass(MenuModel.class).build();
  }

  @Override
  public Long add(OperationMenu operationMenu) {
    ExtAssert.notNull(operationMenu, "对象不存在");
    MenuModel father = new MenuModel();
    if (operationMenu.getSuperId() != null && operationMenu.getSuperId() > 0) {
      father = this.hibernateTemplate.get(MenuModel.class, operationMenu.getSuperId());
      if (father == null) {
        throw new DataModelException("父级分类不存在");
      }
    }
    MenuModel cateModel = new MenuModel();
    ExtBeanUtils.copyProperties(operationMenu, cateModel);
    operationMenu.setId((Long) this.hibernateTemplate.save(cateModel));
    StringBuffer catalogCodeStr = ExtStringUtils.isEmpty(father.getCatalogCode()) ? new StringBuffer() : new StringBuffer(father.getCatalogCode()).append("-");
    cateModel.setCatalogCode(catalogCodeStr.append(operationMenu.getId()).toString());
    return operationMenu.getId();
  }

  @Override
  public void update(OperationMenu operationMenu) {
    if (operationMenu.getSuperId() != null && operationMenu.getSuperId() > 0) {
      MenuModel father = this.hibernateTemplate.get(MenuModel.class, operationMenu.getSuperId());
      if (father == null) {
        throw new DataModelException("父级分类不存在");
      }
      StringBuffer catalogCodeStr = ExtStringUtils.isEmpty(father.getCatalogCode()) ? new StringBuffer() : new StringBuffer(father.getCatalogCode()).append("-");
      operationMenu.setCatalogCode(catalogCodeStr.append(operationMenu.getId()).toString());
    } else {
      operationMenu.setCatalogCode(operationMenu.getId().toString());
    }
    operationMenuRepoHibernateImplTmpl.update(operationMenu);
  }

  @Override
  public void removeById(Long id) {
    String hql = "delete from MenuPermissionModel where menuId = :menuId";
    Query query = operationMenuRepoHibernateImplTmpl.buildQuery(hql);
    query.setLong("menuId", id);
    query.executeUpdate();
    operationMenuRepoHibernateImplTmpl.removeById(id);
  }

  @Override
  public void remove(OperationMenu operationMenu) {
    this.removeById(operationMenu.getId());
  }

  @Override
  public void updateMenuPermission(MenuPermissionModel munePerm) {
    this.hibernateTemplate.saveOrUpdate(munePerm);
  }

  @Override
  public void removeMenuPermissionByIds(Long menuId, List<Long> menuPermsDeleteIds) {
    String hql = "delete from MenuPermissionModel where menuId = :menuId and permissionId in(:permissionIds)";
    Query query = operationMenuRepoHibernateImplTmpl.buildQuery(hql);
    query.setLong("menuId", menuId);
    query.setParameterList("permissionIds", menuPermsDeleteIds);
    query.executeUpdate();
  }

  /*---------------------------------------------------------------------------*/

  @Override
  public OperationMenu getById(Long aLong) {
    return operationMenuRepoHibernateImplTmpl.getById(aLong);
  }

  @Override
  public OperationMenu getOne(Wrapper wrapper) {
    return operationMenuRepoHibernateImplTmpl.getOne(wrapper);
  }

  @Override
  public List<OperationMenu> getList(Wrapper wrapper) {
    return operationMenuRepoHibernateImplTmpl.getList(wrapper);
  }

  @Override
  public List<OperationMenu> findListPage(Wrapper wrapper, Integer startRow, Integer count) {
    return operationMenuRepoHibernateImplTmpl.findListPage(wrapper, startRow, count);
  }

  @Override
  public int getCount(Wrapper wrapper) {
    return operationMenuRepoHibernateImplTmpl.getCount(wrapper);
  }

  @Override
  public boolean contains(Long aLong) {
    return operationMenuRepoHibernateImplTmpl.contains(aLong);
  }

  @Override
  public void fixOldDataCode() {
    IdWorker idWorker = new IdWorker(1);
    List<MenuModel> list = (List<MenuModel>) this.hibernateTemplate.find("from MenuModel model where model.code is null");
    list.forEach(item -> {
      item.setCode(Long.toString(idWorker.nextId(), 32));
    });
  }


}
